#include "pch.hpp"
#include "WidgetStyle.hpp"

using namespace Engine;
using namespace Engine::Ui;




WidgetStyle::WidgetStyle(const ptr& defaultStyle, const AttributeMap& attributes)
	: m_default(1, defaultStyle)
	, m_attributes(attributes)
{}
///////////////////////////////////////////////////////////////////////////////////////////////////

WidgetStyle::~WidgetStyle()
{}
///////////////////////////////////////////////////////////////////////////////////////////////////



bool WidgetStyle::hasAttribute(const Attributes::Type& attr, const WidgetState::Type& state /*= WidgetState::Normal*/) const
{
	AttributeMap::const_iterator i = m_attributes.find(attr);
	if(i == m_attributes.end())
	{
		if(m_default.front())
		{
			return m_default.front()->hasAttribute(attr, state);
		}
		else
		{
			return false;
		}
	}

	return true;
}
///////////////////////////////////////////////////////////////////////////////////////////////////




Border::Type WidgetStyle::borderFromAttribute(Attributes::Type attribute)
{
	switch(attribute)
	{
	case Attributes::ForegroundGlyph:
	case Attributes::BackgroundGlyph:
		return Border::Center;
	case Attributes::BackgroundGlyphTopLeft:
	case Attributes::ForegroundGlyphTopLeft:
		return Border::TopLeft;
	case Attributes::BackgroundGlyphTop:
	case Attributes::ForegroundGlyphTop:
		return Border::Top;
	case Attributes::BackgroundGlyphTopRight:
	case Attributes::ForegroundGlyphTopRight:
		return Border::TopRight;
	case Attributes::BackgroundGlyphRight:
	case Attributes::ForegroundGlyphRight:
		return Border::Right;
	case Attributes::BackgroundGlyphBottomRight:
	case Attributes::ForegroundGlyphBottomRight:
		return Border::BottomRight;
	case Attributes::BackgroundGlyphBottom:
	case Attributes::ForegroundGlyphBottom:
		return Border::Bottom;
	case Attributes::BackgroundGlyphBottomLeft:
	case Attributes::ForegroundGlyphBottomLeft:
		return Border::BottomLeft;
	case Attributes::BackgroundGlyphLeft:
	case Attributes::ForegroundGlyphLeft:
		return Border::Left;
	default:
		BOOSTEXT_THROW(invalid_value_exception(attribute));
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////




const boost::any* WidgetStyle::any_attribute(const Attributes::Type& attr, WidgetState::Type state) const
{
	// Look for that attribute in our map, but if we don't have it,
	// look in the parent (or default) class for that attribute...
	AttributeMap::const_iterator i = m_attributes.find(attr);
	if(i == m_attributes.end())
		return any_attribute_default(attr, state);

	// Now search for the state in that attribute, but also look in the
	// parent if we don't have it (for example it is defined for State::Active here, but
	// for State::Normal in the parent...)
	states::const_iterator o = i->second.end();
	while(o == i->second.end())
	{
		o = i->second.find(state);

		if(state == WidgetState::Normal)
			break;

		uint32 s = state;
		s -= 1;
		state = static_cast<WidgetState::Type>(s);
	}

	if(o == i->second.end())
		return any_attribute_default(attr, state);

	return &o->second;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

const boost::any* WidgetStyle::any_attribute_default(const Attributes::Type& attr, WidgetState::Type state) const
{
	if(m_default.front())
	{
		return m_default.front()->any_attribute(attr, state);
	}
	else
	{
		BOOSTEXT_THROW(attribute_missing_exception(boostext::format("There is no value for the attribute '%1%' at all") % attr));
	}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
